home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 34.zip / BS1 part 34 / FredFish PD 314.adf / Zc / zcsrc.lzh / IOLib / stdio / scanf.c < prev    next >
C/C++ Source or Header  |  1989-05-28  |  8KB  |  424 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3.  
  4. #define FALSE    0
  5. #define TRUE    (!FALSE)
  6.  
  7. extern    char    _numstr[];
  8.  
  9. /* #define    skip()    do{c=(*get)(ip); if (c<1) goto done;}while(isspace(c))*/
  10.  
  11. #define    skip()    while(isspace(c)) { if ((c=(*get)(ip))<1) goto done; }
  12.  
  13. #ifdef FLOATS
  14. /* fp scan actions */
  15. #define F_NADA    0    /* just change state */
  16. #define F_SIGN    1    /* set sign */
  17. #define F_ESIGN    2    /* set exponent's sign */
  18. #define F_INT    3    /* adjust integer part */
  19. #define F_FRAC    4    /* adjust fraction part */
  20. #define F_EXP    5    /* adjust exponent part */
  21. #define F_QUIT    6
  22.  
  23. #define NSTATE    8
  24. #define FS_INIT        0    /* initial state */
  25. #define FS_SIGNED    1    /* saw sign */
  26. #define FS_DIGS        2    /* saw digits, no . */
  27. #define FS_DOT        3    /* saw ., no digits */
  28. #define FS_DD        4    /* saw digits and . */
  29. #define FS_E        5    /* saw 'e' */
  30. #define FS_ESIGN    6    /* saw exp's sign */
  31. #define FS_EDIGS    7    /* saw exp's digits */
  32.  
  33. #define FC_DIG        0
  34. #define FC_DOT        1
  35. #define FC_E        2
  36. #define FC_SIGN        3
  37.  
  38. /* given transition,state do what action? */
  39. int fp_do[][NSTATE] = {
  40.     {F_INT,F_INT,F_INT,
  41.      F_FRAC,F_FRAC,
  42.      F_EXP,F_EXP,F_EXP},    /* see digit */
  43.     {F_NADA,F_NADA,F_NADA,
  44.      F_QUIT,F_QUIT,F_QUIT,F_QUIT,F_QUIT},    /* see '.' */
  45.     {F_QUIT,F_QUIT,
  46.      F_NADA,F_QUIT,F_NADA,
  47.      F_QUIT,F_QUIT,F_QUIT},    /* see e/E */
  48.     {F_SIGN,F_QUIT,F_QUIT,F_QUIT,F_QUIT,
  49.      F_ESIGN,F_QUIT,F_QUIT},    /* see sign */
  50. };
  51. /* given transition,state what is new state? */
  52. int fp_ns[][NSTATE] = {
  53.     {FS_DIGS,FS_DIGS,FS_DIGS,
  54.      FS_DD,FS_DD,
  55.      FS_EDIGS,FS_EDIGS,FS_EDIGS},    /* see digit */
  56.     {FS_DOT,FS_DOT,FS_DD,
  57.      },    /* see '.' */
  58.     {0,0,
  59.      FS_E,0,FS_E,
  60.     },    /* see e/E */
  61.     {FS_SIGNED,0,0,0,0,
  62.      FS_ESIGN,0,0},    /* see sign */
  63. };
  64. /* which states are valid terminators? */
  65. int fp_sval[NSTATE] = {
  66.     0,0,1,0,1,0,0,1
  67. };
  68. #endif
  69.  
  70. _scanf(ip, get, unget, fmt, args)
  71.     register unsigned char *ip;
  72.     int (*get)();
  73.     int (*unget)();
  74.     register unsigned char *fmt;
  75.     char **args;
  76.  
  77.     {
  78.     register long n;
  79.     register int c, width, lval, cnt = 0;
  80.     int store, neg, base, wide1, endnull, rngflag, c2;
  81.     register unsigned char *p;
  82.     unsigned char delim[128], digits[17], *q;
  83.     char *strchr(), *strcpy();
  84. #ifdef FLOATS
  85.     long frac, expo;
  86.     int eneg, fraclen, fstate, trans;
  87.     double fx, fp_scan();
  88. #endif
  89.  
  90.     if (!*fmt)
  91.         return(0);
  92.  
  93.     c = (*get)(ip);
  94.     while(c > 0)
  95.         {
  96.         store = FALSE;
  97.         if (*fmt == '%')
  98.             {
  99.             n    = 0;
  100.             width    = -1;
  101.             wide1    = 1;
  102.             base    = 10;
  103.             lval    = FALSE;
  104.             store    = TRUE;
  105.             endnull    = TRUE;
  106.             neg    = -1;
  107.  
  108.             strcpy(delim,  "\011\012\013\014\015 ");
  109.             strcpy(digits, _numstr); /* "01234567890ABCDEF" */
  110.  
  111.             if (fmt[1] == '*')
  112.                 {
  113.                 endnull = store = FALSE;
  114.                 ++fmt;
  115.                 }
  116.  
  117.             while (isdigit(*++fmt))        /* width digit(s) */
  118.                 {
  119.                 if (width == -1)
  120.                     width = 0;
  121.                 wide1 = width = (width * 10) + (*fmt - '0');
  122.                 }
  123.             --fmt;
  124. fmtnxt:
  125.             ++fmt;
  126.             switch(tolower(*fmt))    /* tolower() is a MACRO! */
  127.                 {
  128.                 case '*':
  129.                     endnull = store = FALSE;
  130.                     goto fmtnxt;
  131.  
  132.                 case 'l':    /* long data */
  133.                     lval = TRUE;
  134. /* for compatability --> */    case 'h':    /* short data */
  135.                     goto fmtnxt;
  136.  
  137.                 case 'i':    /* any-base numeric */
  138.                     base = 0;
  139.                     goto numfmt;
  140.  
  141.                 case 'b':    /* unsigned binary */
  142.                     base = 2;
  143.                     goto numfmt;
  144.  
  145.                 case 'o':    /* unsigned octal */
  146.                     base = 8;
  147.                     goto numfmt;
  148.  
  149.                 case 'x':    /* unsigned hexadecimal */
  150.                     base = 16;
  151.                     goto numfmt;
  152.  
  153.                 case 'd':    /* SIGNED decimal */
  154.                     neg = FALSE;
  155.                     /* FALL-THRU */
  156.  
  157.                 case 'u':    /* unsigned decimal */
  158. numfmt:                    skip();
  159.  
  160.                     if (isupper(*fmt))
  161.                         lval = TRUE;
  162.  
  163.                     if (!base)
  164.                         {
  165.                         base = 10;
  166.                         neg = FALSE;
  167.                         if (c == '%')
  168.                             {
  169.                             base = 2;
  170.                             goto skip1;
  171.                             }
  172.                         else if (c == '0')
  173.                             {
  174.                             c = (*get)(ip);
  175.                             if (c < 1)
  176.                                 goto savnum;
  177.                             if ((c != 'x')
  178.                              && (c != 'X'))
  179.                                 {
  180.                                 base = 8;
  181.                                 digits[8]= '\0';
  182.                                 goto zeroin;
  183.                                 }
  184.                             base = 16;
  185.                             goto skip1;
  186.                             }
  187.                         }
  188.  
  189.                     if ((neg == FALSE) && (base == 10)
  190.                      && ((neg = (c == '-')) || (c == '+')))
  191.                         {
  192. skip1:
  193.                         c = (*get)(ip);
  194.                         if (c < 1)
  195.                             goto done;
  196.                         }
  197.  
  198.                     digits[base] = '\0';
  199.                     p = ((unsigned char *)
  200.                         strchr(digits,toupper(c)));
  201.  
  202.                     if ((!c || !p) && width)
  203.                         goto done;
  204.  
  205.                     while (p && width-- && c)
  206.                         {
  207.                         n = (n * base) + (p - digits);
  208.                         c = (*get)(ip);
  209. zeroin:
  210.                         p = ((unsigned char *)
  211.                         strchr(digits,toupper(c)));
  212.                         }
  213. savnum:
  214.                     if (store)
  215.                         {
  216.                         p = ((unsigned char *) *args);
  217.                         if (neg == TRUE)
  218.                             n = -n;
  219.                         if (lval)
  220.                             *((long*) p) = n;
  221.                         else
  222.                             *((int *) p) = n;
  223.                         ++cnt;
  224.                         }
  225.                     break;
  226.  
  227. #ifdef FLOATS
  228.                 case 'e':    /* float */
  229.                 case 'f':
  230.                 case 'g':
  231.                     skip();
  232.  
  233.                     if (isupper(*fmt))
  234.                         lval = TRUE;
  235.  
  236.                     fstate = FS_INIT;
  237.                     neg = FALSE;  eneg = FALSE;
  238.                     n = 0;  frac = 0;  expo = 0;
  239.                     fraclen = 0;
  240.  
  241.                     while (c && width--) {
  242.                         if (c >= '0' && c <= '9')
  243.                             trans = FC_DIG;
  244.                         else if (c == '.')
  245.                             trans = FC_DOT;
  246.                         else if (c == '+' || c == '-')
  247.                             trans = FC_SIGN;
  248.                         else if (tolower(c) == 'e')
  249.                             trans = FC_E;
  250.                         else
  251.                             goto fdone;
  252.  
  253.                         switch (fp_do[trans][fstate]) {
  254.                         case F_SIGN:
  255.                             neg = (c == '-');
  256.                             break;
  257.                         case F_ESIGN:
  258.                             eneg = (c == '-');
  259.                             break;
  260.                         case F_INT:
  261.                             n = 10*n + (c - '0');
  262.                             break;
  263.                         case F_FRAC:
  264.                            frac = 10*frac + (c - '0');
  265.                             fraclen++;
  266.                             break;
  267.                         case F_EXP:
  268.                            expo = 10*expo + (c - '0');
  269.                             break;
  270.                         case F_QUIT:
  271.                             goto fdone;
  272.                         }
  273.                         fstate = fp_ns[trans][fstate];
  274.                         c = (*get)(ip);
  275.                     }
  276.  
  277. fdone:
  278.                     if (!fp_sval[fstate])
  279.                         goto done;
  280.                     if (store) {
  281.                         fx = fp_scan(neg, eneg,
  282.                             n, frac, expo, fraclen);
  283.                         p = (unsigned char *) *args;
  284.                         if (lval)
  285.                             *((double *) p) = fx;
  286.                         else
  287.                             *((float *) p) = fx;
  288.                         ++cnt;
  289.                     }
  290.                     break;
  291. #endif
  292.  
  293.                 case 'c':    /* character data */
  294.                     width = wide1;
  295.                     endnull    = FALSE;
  296.                     delim[0] = '\0';
  297.                     goto strproc;
  298.  
  299.                 case '[':    /* string w/ delimiter set */
  300.  
  301.                     /* get delimiters */
  302.                     p = delim;
  303.  
  304.                     if (*++fmt == '^')
  305.                         fmt++;
  306.                     else
  307.                         lval = TRUE;
  308.  
  309.                     rngflag = 2;
  310.                     if ((*fmt == ']') || (*fmt == '-'))
  311.                         {
  312.                         *p++ = *fmt++;
  313.                         rngflag = FALSE;
  314.                         }
  315.  
  316.                     while (*fmt != ']')
  317.                         {
  318.                         if (*fmt == '\0')
  319.                             goto done;
  320.                         switch (rngflag)
  321.                             {
  322.                             case TRUE:
  323.                             c2 = *(p-2);
  324.                             if (c2 <= *fmt)
  325.                                 {
  326.                                 p -= 2;
  327.                                 while (c2 < *fmt)
  328.                                     *p++ = c2++;
  329.                                 rngflag = 2;
  330.                                 break;
  331.                                 }
  332.                             /* fall thru intentional */
  333.  
  334.                             case FALSE:
  335.                             rngflag = (*fmt == '-');
  336.                             break;
  337.  
  338.                             case 2:
  339.                             rngflag = FALSE;
  340.                             }
  341.  
  342.                         *p++ = *fmt++;
  343.                         }
  344.  
  345.                     *p = '\0';
  346.                     goto strproc;
  347.  
  348.                 case 's':    /* string data */
  349.                     skip();
  350. strproc:
  351.                     /* process string */
  352.                     p = ((unsigned char *) *args);
  353.  
  354.                     /* if the 1st char fails, match fails */
  355.                     if (width)
  356.                         {
  357.                         q = ((unsigned char *)
  358.                             strchr(delim, c));
  359.                         if((c < 1)
  360.                         || (lval ? !q : (int) q))
  361.                             {
  362.                             if (endnull)
  363.                                 *p = '\0';
  364.                             goto done;
  365.                             }
  366.                         }
  367.  
  368.                     for (;;) /* FOREVER */
  369.                         {
  370.                         if (store)
  371.                             *p++ = c;
  372.                         if (((c = (*get)(ip)) < 1) ||
  373.                             (--width == 0))
  374.                             break;
  375.  
  376.                         q = ((unsigned char *)
  377.                             strchr(delim, c));
  378.                         if (lval ? !q : (int) q)
  379.                             break;
  380.                         }
  381.  
  382.                     if (store)
  383.                         {
  384.                         if (endnull)
  385.                             *p = '\0';
  386.                         ++cnt;
  387.                         }
  388.                     break;
  389.  
  390.                 case '\0':    /* early EOS */
  391.                     --fmt;
  392.                     /* FALL THRU */
  393.  
  394.                 default:
  395.                     goto cmatch;
  396.                 }
  397.             }
  398.         else if (isspace(*fmt))        /* skip whitespace */
  399.             {
  400.             skip();
  401.             }
  402.         else 
  403.             {            /* normal match char */
  404. cmatch:
  405.             if (c != *fmt) 
  406.                 break;
  407.             c = (*get)(ip);
  408.             }
  409.  
  410.         if (store)
  411.             args++;
  412.  
  413.         if (!*++fmt)
  414.             break;
  415.         }
  416.  
  417. done:                        /* end of scan */
  418.     if ((c < 0) && (cnt == 0))
  419.         return(EOF);
  420.  
  421.     (*unget)(c, ip);
  422.     return(cnt);
  423.     }
  424.